home *** CD-ROM | disk | FTP | other *** search
/ Oh!X 2000 Spring / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 2).7z / Oh!X 2000 Spring Special CD-ROM (Japan) (Part 2).bin / DXF / samples / multimedia / dsound / src / voicemanagement / voicemanagement.cpp < prev    next >
C/C++ Source or Header  |  1999-08-02  |  11KB  |  377 lines

  1. //-----------------------------------------------------------------------------
  2. // File: VoiceManagement.cpp
  3. //
  4. // Desc: DirectSound support file for sample showing how to load a wave file 
  5. //       and play it using a system RAM DirectSound buffer with
  6. //       voice management flags
  7. //
  8. // Copyright (c) 1999 Microsoft Corp. All rights reserved.
  9. //-----------------------------------------------------------------------------
  10. #define STRICT
  11. #include <objbase.h>
  12. #include <initguid.h>
  13. #include <commdlg.h>
  14. #include <mmreg.h>
  15. #include <dsound.h>
  16. #include "resource.h"
  17. #include "WavRead.h"
  18.  
  19.  
  20.  
  21.  
  22. //-----------------------------------------------------------------------------
  23. // Function-prototypes
  24. //-----------------------------------------------------------------------------
  25. extern VOID EnablePlayUI( HWND hDlg, BOOL bShowPlayControl );
  26. extern VOID SetFileUI( HWND hDlg, TCHAR* strFileName );
  27.  
  28. VOID LoadWaveFile( HWND hDlg, TCHAR* strFileName );
  29. HRESULT CreateSystemRAMBuffer( HWND hDlg, TCHAR* strFileName );
  30. HRESULT FillBuffer();
  31. HRESULT RestoreBuffers();
  32.  
  33.  
  34.  
  35.  
  36. //-----------------------------------------------------------------------------
  37. // Defines, constants, and global variables
  38. //-----------------------------------------------------------------------------
  39. #define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
  40. #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
  41.  
  42. LPDIRECTSOUND       g_pDS            = NULL;
  43. LPDIRECTSOUNDBUFFER g_pDSBuffer      = NULL;
  44. LPDIRECTSOUNDNOTIFY g_pDSNotify      = NULL;
  45. CWaveSoundRead*     g_pWaveSoundRead = NULL;
  46. DWORD               g_dwBufferBytes;
  47.  
  48.  
  49.  
  50. //-----------------------------------------------------------------------------
  51. // Name: InitDirectSound()
  52. // Desc: Initilizes DirectSound
  53. //-----------------------------------------------------------------------------
  54. HRESULT InitDirectSound( HWND hDlg )
  55. {
  56.     HRESULT             hr;
  57.     LPDIRECTSOUNDBUFFER pDSBPrimary = NULL;
  58.  
  59.     // Initialize COM
  60.     if( hr = CoInitialize( NULL ) )
  61.         return hr;
  62.  
  63.     // Create IDirectSound using the primary sound device
  64.     if( FAILED( hr = DirectSoundCreate( NULL, &g_pDS, NULL ) ) )
  65.         return hr;
  66.  
  67.     // Set coop level to DSSCL_PRIORITY
  68.     if( FAILED( hr = g_pDS->SetCooperativeLevel( hDlg, DSSCL_PRIORITY ) ) )
  69.         return hr;
  70.  
  71.     // Get the primary buffer 
  72.     DSBUFFERDESC dsbd;
  73.     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  74.     dsbd.dwSize        = sizeof(DSBUFFERDESC);
  75.     dsbd.dwFlags       = DSBCAPS_PRIMARYBUFFER;
  76.     dsbd.dwBufferBytes = 0;
  77.     dsbd.lpwfxFormat   = NULL;
  78.        
  79.     if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) )
  80.         return hr;
  81.  
  82.     // Set primary buffer format to 22kHz and 16-bit output.
  83.     WAVEFORMATEX wfx;
  84.     ZeroMemory( &wfx, sizeof(WAVEFORMATEX) ); 
  85.     wfx.wFormatTag      = WAVE_FORMAT_PCM; 
  86.     wfx.nChannels       = 2; 
  87.     wfx.nSamplesPerSec  = 22050; 
  88.     wfx.wBitsPerSample  = 16; 
  89.     wfx.nBlockAlign     = wfx.wBitsPerSample / 8 * wfx.nChannels;
  90.     wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
  91.  
  92.     if( FAILED( hr = pDSBPrimary->SetFormat(&wfx) ) )
  93.         return hr;
  94.  
  95.     SAFE_RELEASE( pDSBPrimary );
  96.  
  97.     return S_OK;
  98. }
  99.  
  100.  
  101.  
  102.  
  103. //-----------------------------------------------------------------------------
  104. // Name: FreeDirectSound()
  105. // Desc: Releases DirectSound 
  106. //-----------------------------------------------------------------------------
  107. HRESULT FreeDirectSound()
  108. {
  109.     SAFE_DELETE( g_pWaveSoundRead );
  110.  
  111.     // Release DirectSound interfaces
  112.     SAFE_RELEASE( g_pDSBuffer );
  113.     SAFE_RELEASE( g_pDS ); 
  114.  
  115.     // Release COM
  116.     CoUninitialize();
  117.  
  118.     return S_OK;
  119. }
  120.  
  121.  
  122.  
  123.  
  124. //-----------------------------------------------------------------------------
  125. // Name: LoadWaveFile()
  126. // Desc: Loads the wave file into a secondary system RAM DirectSound buffer
  127. //-----------------------------------------------------------------------------
  128. VOID LoadWaveFile( HWND hDlg, TCHAR* strFileName )
  129. {
  130.     // Create the sound buffer object from the wave file data
  131.     if( FAILED( CreateSystemRAMBuffer( hDlg, strFileName ) ) )
  132.     {        
  133.         SetFileUI( hDlg, TEXT("Couldn't create sound buffer.") ); 
  134.     }
  135.     else // The sound buffer was successfully created
  136.     {
  137.         // Fill the buffer with wav data
  138.         FillBuffer();
  139.  
  140.         // Update the UI controls to show the sound as the file is loaded
  141.         SetFileUI( hDlg, strFileName );
  142.         EnablePlayUI( hDlg, TRUE );
  143.     }
  144. }
  145.  
  146.  
  147.  
  148.  
  149. //-----------------------------------------------------------------------------
  150. // Name: CreateSystemRAMBuffer()
  151. // Desc: Creates a wave file, sound buffer and notification events 
  152. //-----------------------------------------------------------------------------
  153. HRESULT CreateSystemRAMBuffer( HWND hDlg, TCHAR* strFileName )
  154. {
  155.     HRESULT hr; 
  156.  
  157.     // Free any previous globals 
  158.     SAFE_DELETE( g_pWaveSoundRead );
  159.     SAFE_RELEASE( g_pDSBuffer );
  160.  
  161.     // Create a new wave file class
  162.     g_pWaveSoundRead = new CWaveSoundRead();
  163.  
  164.     // Load the wave file
  165.     if( FAILED( g_pWaveSoundRead->Open( strFileName ) ) )
  166.     {
  167.         SetFileUI( hDlg, TEXT("Bad wave file.") );
  168.     }
  169.  
  170.     // Set up the direct sound buffer
  171.     // DSBCAPS_LOCDEFER must be specificed since this allows the 
  172.     // buffer to at Play() time to go into either a software 
  173.     // or hardware buffer. 
  174.     //
  175.     // Not specifing the DSBCAPS_STATIC flag will put the buffer in 
  176.     // system RAM instead of sound card RAM.  This will typically 
  177.     // be more efficent for voice management buffers since newer 
  178.     // generation PCI audio cards all use system memory for their 
  179.     // hardware buffers, and by creating our buffers in system RAM 
  180.     // buffers, we're guarenteed the highest performance using the 
  181.     // DSBCAPS_LOCDEFER flag.  Because of the download time, we 
  182.     // don't want to use DEFER'd buffers on older ISA sound cards 
  183.     // with their own memory
  184.     DSBUFFERDESC dsbd;
  185.     ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
  186.     dsbd.dwSize        = sizeof(DSBUFFERDESC);
  187.     dsbd.dwFlags       = DSBCAPS_LOCDEFER;
  188.     dsbd.dwBufferBytes = g_pWaveSoundRead->m_ckIn.cksize;
  189.     dsbd.lpwfxFormat   = g_pWaveSoundRead->m_pwfx;
  190.  
  191.     // Create the static DirectSound buffer 
  192.     if( FAILED( hr = g_pDS->CreateSoundBuffer( &dsbd, &g_pDSBuffer, NULL ) ) )
  193.         return hr;
  194.  
  195.     // Remember how big the buffer is
  196.     g_dwBufferBytes = dsbd.dwBufferBytes;
  197.  
  198.     return S_OK;
  199. }
  200.  
  201.  
  202.  
  203.  
  204. //-----------------------------------------------------------------------------
  205. // Name: FillBuffer()
  206. // Desc: Fill the DirectSound buffer with data from the wav file
  207. //-----------------------------------------------------------------------------
  208. HRESULT FillBuffer()
  209. {
  210.     HRESULT hr; 
  211.     BYTE*   pbWavData; // Pointer to actual wav data 
  212.     UINT    cbWavSize; // Size of data
  213.     VOID*   pbData  = NULL;
  214.     VOID*   pbData2 = NULL;
  215.     DWORD   dwLength;
  216.     DWORD   dwLength2;
  217.  
  218.     // The size of wave data is in pWaveFileSound->m_ckIn
  219.     INT nWaveFileSize = g_pWaveSoundRead->m_ckIn.cksize;
  220.  
  221.     // Allocate that buffer.
  222.     pbWavData = new BYTE[ nWaveFileSize ];
  223.     if( NULL == pbWavData )
  224.         return E_OUTOFMEMORY;
  225.  
  226.     if( FAILED( hr = g_pWaveSoundRead->Read( nWaveFileSize, 
  227.                                              pbWavData, 
  228.                                              &cbWavSize ) ) )           
  229.         return hr;
  230.  
  231.     // Reset the file to the beginning 
  232.     g_pWaveSoundRead->Reset();
  233.  
  234.     // Lock the buffer down
  235.     if( FAILED( hr = g_pDSBuffer->Lock( 0, g_dwBufferBytes, &pbData, &dwLength, 
  236.                                    &pbData2, &dwLength2, 0L ) ) )
  237.         return hr;
  238.  
  239.     // Copy the memory to it.
  240.     memcpy( pbData, pbWavData, g_dwBufferBytes );
  241.  
  242.     // Unlock the buffer, we don't need it anymore.
  243.     g_pDSBuffer->Unlock( pbData, g_dwBufferBytes, NULL, 0 );
  244.     pbData = NULL;
  245.  
  246.     // We dont need the wav file data buffer anymore, so delete it 
  247.     SAFE_DELETE( pbWavData );
  248.  
  249.     return S_OK;
  250. }
  251.  
  252.  
  253.  
  254.  
  255. //-----------------------------------------------------------------------------
  256. // Name: PlayBuffer()
  257. // Desc: User hit the "Play" button, so play the DirectSound buffer
  258. //-----------------------------------------------------------------------------
  259. BOOL IsBufferPlaying() 
  260. {
  261.     DWORD dwStatus = 0;
  262.  
  263.     if( NULL == g_pDSBuffer )
  264.         return E_FAIL;
  265.  
  266.     g_pDSBuffer->GetStatus( &dwStatus );
  267.  
  268.     if( dwStatus & DSBSTATUS_PLAYING )
  269.         return TRUE;
  270.     else 
  271.         return FALSE;
  272. }
  273.  
  274.  
  275.  
  276.  
  277. //-----------------------------------------------------------------------------
  278. // Name: PlayBuffer()
  279. // Desc: User hit the "Play" button, so play the DirectSound buffer
  280. //-----------------------------------------------------------------------------
  281. HRESULT PlayBuffer( DWORD dwPriority, DWORD dwPlayFlags )
  282. {
  283.     HRESULT hr;
  284.  
  285.     if( NULL == g_pDSBuffer )
  286.         return E_FAIL;
  287.  
  288.     // Restore the buffers if they are lost
  289.     if( FAILED( hr = RestoreBuffers() ) )
  290.         return hr;
  291.  
  292.     // Play buffer 
  293.     if( FAILED( hr = g_pDSBuffer->Play( 0, dwPriority, dwPlayFlags ) ) )
  294.         return hr;
  295.  
  296.     return S_OK;
  297. }
  298.  
  299.  
  300.  
  301.  
  302. //-----------------------------------------------------------------------------
  303. // Name: StopBuffer()
  304. // Desc: Stop the DirectSound buffer from playing 
  305. //-----------------------------------------------------------------------------
  306. VOID StopBuffer( BOOL bResetPosition ) 
  307. {
  308.     if( NULL == g_pDSBuffer )
  309.         return;
  310.  
  311.     g_pDSBuffer->Stop();
  312.  
  313.     if( bResetPosition )
  314.         g_pDSBuffer->SetCurrentPosition( 0L );    
  315. }
  316.  
  317.  
  318.  
  319.  
  320. //-----------------------------------------------------------------------------
  321. // Name: IsSoundPlaying()
  322. // Desc: Checks to see if a sound is playing and returns TRUE if it is.
  323. //-----------------------------------------------------------------------------
  324. BOOL IsSoundPlaying()
  325. {
  326.     if( g_pDSBuffer )
  327.     {  
  328.         DWORD dwStatus = 0;
  329.         g_pDSBuffer->GetStatus( &dwStatus );
  330.         return( ( dwStatus & DSBSTATUS_PLAYING ) != 0 );
  331.     }
  332.     else
  333.     {
  334.         return FALSE;
  335.     }
  336. }
  337.  
  338.  
  339.  
  340.  
  341. //-----------------------------------------------------------------------------
  342. // Name: RestoreBuffers()
  343. // Desc: Restore lost buffers and fill them up with sound if possible
  344. //-----------------------------------------------------------------------------
  345. HRESULT RestoreBuffers()
  346. {
  347.     HRESULT hr;
  348.  
  349.     if( NULL == g_pDSBuffer )
  350.         return S_OK;
  351.  
  352.     DWORD dwStatus;
  353.     if( FAILED( hr = g_pDSBuffer->GetStatus( &dwStatus ) ) )
  354.         return hr;
  355.  
  356.     if( dwStatus & DSBSTATUS_BUFFERLOST )
  357.     {
  358.         // Since the app could have just been activated, then
  359.         // DirectSound may not be giving us control yet, so 
  360.         // the restoring the buffer may fail.  
  361.         // If it does, sleep until DirectSound gives us control.
  362.         do 
  363.         {
  364.             hr = g_pDSBuffer->Restore();
  365.             if( hr == DSERR_BUFFERLOST )
  366.                 Sleep( 10 );
  367.         }
  368.         while( hr = g_pDSBuffer->Restore() );
  369.  
  370.         if( FAILED( hr = FillBuffer() ) )
  371.             return hr;
  372.     }
  373.  
  374.     return S_OK;
  375. }
  376.  
  377.